/**
 *
 * 通用单资源(模型、表)CURD
 *
 * */
import type { NextFunction, Request, Response } from "express";
import * as commSvc from "../services/common.service";
import { registerRpcMethod, type TRpcMethod } from "./core";
import { checkResouceActionAuth, ENUM_ACTION } from "../models";
import assert from "assert";
import MessageCode from "../validators/core/MessageCode";
import { commLog } from "../utils/log";

// 通用方法请求
export interface IReqRest {
  resource: string; // 资源名称
  action: commSvc.IAction; // 动作
  options: commSvc.IReqRestOptions; // 请求选项
}

const singleResouceCommonCRUD: TRpcMethod = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const { resource, action, options } = req.body.params;

  // 权限检查
  assert(
    checkResouceActionAuth(resource, action),
    MessageCode.Public.resource.invalidAction
  );

  // 资源名称转换为模型
  const modelFile = `../models/${resource}.model`;
  const model = require(modelFile).default;
  assert(model, MessageCode.Public.resource.notFound);

  const validFile = `../../validators/${resource}.valid.ts`;
  commLog.debug(validFile);

  // 解构出 IReqRestOptions 对象中的 data
  const { data } = options;

  switch (action) {
    case ENUM_ACTION.LIST: // 查询资源列表
      req.data = await commSvc._list(model, options);
      break;
    case ENUM_ACTION.ONE: // 根据ID查询资源
      req.data = await commSvc._oneForId(
        model,
        data as commSvc.IReqQueryByIdOptions
      );
      break;
    case ENUM_ACTION.CREATE_ONE: // 创建单个资源
      // 资源名称转换为验证器
      require(validFile).default.create.parse(data);
      req.data = await commSvc._createOne(model, data);
      break;
    case ENUM_ACTION.CREATE_MANY: // 创建多个资源
      req.data = await commSvc._createMany(model, data);
      break;
    case ENUM_ACTION.UPDATE: // 更新资源
      // 资源名称转换为验证器
      commLog.debug(data);

      require(validFile).default.update.parse(data);
      const udpRecord = data as IDynamicProp<any>;
      req.data = await commSvc._updateForId(model, udpRecord._id, udpRecord);
      break;
    case ENUM_ACTION.DELETE: // 删除资源
      // 资源名称转换为验证器
      require(validFile).default.delete.parse(data);
      await commSvc._removeForId(model, (data as IDynamicProp<string>)._id);
      break;
    default:
      assert(false, MessageCode.Public.resource.invalidAction);
  }

  next();
};

registerRpcMethod([
  {
    desc: `
/** 
*
* ### 单资源通用增删改查 - 接口需要签权后调用
* 
* \`\`\` typescript
* 
* // 前置类型-动态属性对象
* interface IDynamicProp<T> {
*   [key: string]: T,
* }
* 
* // 前置类型-根据_id查询单条数据
* export interface IReqQueryByIdOptions {
*   _id: string, // 资源ID
*   fill: string, // 需要填充的字段，目前只支持1级填充，多个字段使用 空格 分隔
* }
* 
* // 前置类型-查询请求选项
* export interface IReqRestOptions {
*   query?: any, // 查询条件
*   field?: string, // 字段, 多个字段使用 空格 分隔
*   fill?: string | string[] | Object, // 指定字段填充
*   sort?: IDynamicProp<1 | -1>, // 排序字段, 1 升序 -1 降序
*   pagin?: {
*     page: number, // 当前页码
*     pagesize: number, // 每页条数
*   },
*   data?: string | number | Object | IReqQueryByIdOptions, // 请求数据，用于单id搜索、创建、更新、以及删除
* }
* 

* 
* // 请求参数
* interface IReqRest {
*   resource: string; // 资源名称
*   action: 'list' | 'id' | 'create' | 'update' | 'delete', // 动作
*   options: IReqQueryOptions | IReqQueryByIdOptions, // 请求选项
* }
* 
* \`\`\`
*/`,
    name: singleResouceCommonCRUD.name,
    method: singleResouceCommonCRUD,
    auth: true,
  },
]);
